#ifndef __CAPACONSULTA_ADMINISTRADORDEOPERACIONES_H
#define __CAPACONSULTA_ADMINISTRADORDEOPERACIONES_H

/*****************************************************************************
*                     Organizacion de Datos - 75.06                          *
*                         Catedra Lic. Servetto                              *
*            Facultad de Ingenieria - Universidad de Buenos Aires            *
******************************************************************************/

#include "ConexionCapaMetadata.h"
#include "../Comun/Archivo.h"
#include "../Comun/Condiciones.h"
#include "../Comun/Clase.h"


using namespace std;
using namespace Comun;

namespace CapaConsulta
{
	
	struct ClaseAtributo
	{
		string NombreClase;
		string NombreAtributo;
	};

	struct Join
	{
		ClaseAtributo From;
		ClaseAtributo ClaseJoin;
		bool Leido;		
	};

	/// Representa una operacion realizada sobre la Capa de Metadata
	class Operacion
	{

	public:

		// Constructor y Destructor
		Operacion();
		virtual ~Operacion();

		// Miembros
		Clase *ClaseOperacion;
		CondicionCompuesta *Condiciones;
		list<ClaveValor>* Valores;


		/// Ejecuta la operacion.
		/// @return booleano indicado si la operaci�n fue exitosa o no.
		virtual bool Ejecutar() = 0;		
		/// Obtiene el resultado de la operacion, que incluye las instancias leidas, codigos y mensajes de error.
		virtual Resultado* ObtenerResultado() = 0;

	protected:
		Resultado* resultado;
	};
	
	/// Representa una operacion de insercion, palabra clave INSERT
	class Insercion : public Operacion
	{
	public:

		Insercion();
		~Insercion();

		bool Ejecutar();
		Resultado* ObtenerResultado();

	};
	
	/// Representa una operacion de borrado, palabra clave DELETE
	class Borrado : public  Operacion 
	{
	public:

		Borrado();
		~Borrado();

		bool Ejecutar();
		Resultado* ObtenerResultado();
	};
	
	/// Representa una operacion de actualizacion, palabra clave UPDATE
	class Actualizacion : public Operacion
	{
	public:

		Actualizacion();
		~Actualizacion();

		bool Ejecutar();
		Resultado* ObtenerResultado();
	};
	
	/// Representa una operacion de seleccion, palabra clave SELECT
	class Seleccion : public Operacion
	{

	public:
		Seleccion();
		~Seleccion();

		bool Ejecutar();
		Resultado* ObtenerResultado();

		// Clase unida en la seleccion. Su valor puede ser nulo
		Clase* ClaseJoin;
		// Nombre del miembro de la clase (base o join) por el cual sera ordenado el resultado.
		Atributo* OrdernarPor;

		Atributo* CampoJoin;
		Atributo* CampoJoinFrom;

		list<Join>* Joins;

		list<string>* CamposSeleccion;
		list<ClaseAtributo>* CamposSeleccionConClase;

		string NombreArchivoResultado;
		
		bool OrdenarAscendente;

	private:
		Clase* ClaseConCondicionFuerte();
		bool EjecutarJoin(Clase* claseFuerte);
		list<Clase*>* Clases;
		list<Registro*>* TraerCamposDeJoin(Registro* i, string claseFuerte);
		list<Registro*>* SeleccionJoin(string claseFuerte, ClaseAtributo claseJoin, ClaseAtributo from,list<Registro*>* aux);
		void OrdenarExterno(string* archivoResultado, Atributo* ordenarPor, bool asc);
		bool primerJoin;
	};
	
	/// Representa una operacion de creacion de una clase, palabra clave CREATE
	class CrearClase : public  Operacion
	{
	public:
		CrearClase();
		~CrearClase();

		bool Ejecutar();
		Resultado* ObtenerResultado();

		// Path al archivo que contiene la metadata de creacion
		string* PathArchivoCreacion;
	};
	
	/// Representa una ejecucion de un comando de consola, palabra clave EXECUTE
	class EjecutarComando : public  Operacion
	{
	public:
		EjecutarComando();
		~EjecutarComando();

		bool Ejecutar();
		Resultado* ObtenerResultado();

		// Comando a ejecutar
		string* Comando;
	};

	/// Administra las operaciones y maneja la conexion con la capa de Metadata, e interpreta el resultado de cada operacionn.
	class AdministradorDeOPeraciones
	{
	private:
		// Singleton
		static AdministradorDeOPeraciones* instancia;

	protected:

		// El contructor y detructuctor es protegido por que la vida de las instancias es mantenida por el propio objeto.
		AdministradorDeOPeraciones();
		~AdministradorDeOPeraciones();

	public:

		/// Metodo estatico que crea si es que no existe por primera vez una instancia del AdministradorDeArchivos o utiliza la que ya tiene en memoria. En el momento de la primera instanciacion las definicion de clases es leida de un archivo en disco.
		/// @return Devuelve la instacia del AdministradorDeArchivos
		static AdministradorDeOPeraciones* Instancia();

		Insercion* CrearOperacionInsercion(Clase* clase, CondicionCompuesta* condiciones );

		Borrado* CrearOperacionBorrado(Clase* clase, CondicionCompuesta* condiciones);

		Seleccion* CrearOperacionSeleccion(Clase* clase, CondicionCompuesta* condiciones);

		Actualizacion* CrearOperacionActualizacion(Clase* clase, CondicionCompuesta* condiciones);

		CrearClase* CrearOperacionCrearClase(Clase* clase, CondicionCompuesta* condiciones);

	};
	
}

#endif
